package com.weilf.zookeeper.lock;

import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 分布式锁相关的回调封装
 * @author weil-f
 * @date 2021/2/7 9:56
 */
@Slf4j
public class LockWatcher implements AsyncCallback.StringCallback, Watcher, AsyncCallback.Children2Callback , AsyncCallback.StatCallback {

	private ZooKeeper zk;

	private String threadName;

	private String pathName;


	private CountDownLatch cc  = new CountDownLatch(1);



	public void setThreadName(String threadName) {
		this.threadName = threadName;
	}

	public void setZk(ZooKeeper zk) {
		this.zk = zk;
	}



	/**
	 * 获得锁
	 */
	public void tryLock(){
		zk.create("/lock",threadName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,this,"abcd");
		try {
			cc.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 释放锁
	 */
	public void unLock(){
		try {
			zk.delete(pathName,-1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (KeeperException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 创建节点的回调
	 * @param rc
	 * @param path
	 * @param ctx
	 * @param name
	 */
	public void processResult(int rc, String path, Object ctx, String name) {
		if (null != name){
			log.info("临时有序节点创建成功,线程名称为===>{}节点名称为===>{}",threadName,name);
			pathName = name;
				// 获取父亲节点的 所有孩子节点
			zk.getChildren("/",this,this,"abc");

		}
	}

	public void process(WatchedEvent event) {
		switch (event.getType()) {
			case None:
				break;
			case NodeCreated:
				break;
			case NodeDeleted:
				zk.getChildren("/",false,this ,"sdf");
				break;
			case NodeDataChanged:
				break;
			case NodeChildrenChanged:
				break;
		}
	}


	/**
	 * 获取孩子节点的回调
	 * @param rc
	 * @param path
	 * @param ctx
	 * @param children 所有的子节点
	 * @param stat
	 */
	public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
		Collections.sort(children);
		int i = children.indexOf(pathName.substring(1));
		if (i == 0){
			log.info("线程名称===>{},是第一个",threadName);
			try {
				zk.setData("/",threadName.getBytes(),-1);
				cc.countDown();
			} catch (KeeperException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}else {
			zk.exists("/"+children.get(i-1),this,this,"aaa");
		}

	}

	public void processResult(int rc, String path, Object ctx, Stat stat) {

	}
}
